'''
Created on 17/10/2011

@author: Daniel
'''
#Classe extraida do python cookbook... ainda nao foi testada!
class Cpf:
    def __init__(self, cpf):
        """Classe representando um numero de CPF

        >>> a = CPF('95524361503')
        >>> b = CPF('955.243.615-03')
        >>> c = CPF([9, 5, 5, 2, 4, 3, 6, 1, 5, 0, 3])

        """

        try:
            basestring
        except:
            basestring = (str, unicode)

        if isinstance(cpf, basestring):
            cpf = cpf.replace(".", "")
            cpf = cpf.replace("-", "")
            if not cpf.isdigit():
                raise ValueError("Valor nao segue a forma xxx.xxx.xxx-xx")
            
        if len(cpf) < 11:
            raise ValueError("O numero de CPF deve ter 11 digitos")

        self.cpf = map(int, cpf)


    def __getitem__(self, index):
        """Retorna o digito em index como string

        >>> a = CPF('95524361503')
        >>> a[9] == '0'
        True
        >>> a[10] == '3'
        True
        >>> a[9] == 0
        False
        >>> a[10] == 3
        False

        """
        return str(self.cpf[index])

    def __repr__(self):
        """Retorna uma representacao 'real', ou seja:

        eval(repr(cpf)) == cpf

        >>> a = CPF('95524361503')
        >>> print repr(a)
        CPF('95524361503')
        >>> eval(repr(a)) == a
        True
        
        """
        return "CPF('%s')" % ''.join([str(x) for x in self.cpf])

    def __eq__(self, other):
        """Prove teste de igualdade para numeros de CPF

        >>> a = CPF('95524361503')
        >>> b = CPF('955.243.615-03')
        >>> c = CPF('123.456.789-00')
        >>> a == b
        True
        >>> a != c
        True
        >>> b != c
        True

        """
        if isinstance(other, Cpf):
            return self.cpf == other.cpf
        return False
    
    def __str__(self):
        """Retorna uma string do CPF na forma com pontos e traco

        >>> a = CPF('95524361503')
        >>> str(a)
        '955.243.615-03'
        

        """
        d = ((3, "."), (7, "."), (11, "-"))
        s = map(str, self.cpf)
        for i, v in d:
            s.insert(i, v)
        r = ''.join(s)
        return r

    def valido(self):
        """Valida o numero de cpf

        >>> a = CPF('95524361503')
        >>> a.valido()
        True
        >>> b = CPF('12345678900')
        >>> b.valido()
        False

        """
        cpf = self.cpf[:9]
        # pegamos apenas os 9 primeiros digitos do cpf e geramos os
        # dois digitos que faltam
        while len(cpf) < 11:

            r = sum(map(lambda(i,v):(len(cpf)+1-i)*v,enumerate(cpf))) % 11

            if r > 1:
                f = 11 - r
            else:
                f = 0
            cpf.append(f)

        # se o numero com os digitos faltantes coincidir com o numero
        # original, entao ele e valido
        return bool(cpf == self.cpf)

    def __nonzero__(self):
        """Valida o numero de cpf
        
        >>> a = CPF('95524361503')
        >>> bool(a)
        True
        >>> b = CPF('12345678900')
        >>> bool(b)
        False
        >>> if a:
        ...     print 'OK'
        ... 
        OK

        >>> if b:
        ...     print 'OK'
        ... 
        >>>
        """

        return self.valido()



if __name__ == "__main__":

    import doctest, sys
    doctest.testmod(sys.modules[__name__])


a = Cpf("08784652438")
a.valido()